import json
import re

from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.hashers import check_password
from django.http import JsonResponse

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from apps.cart.utils import merge_cart_cookie_to_redis
from apps.users.models import User, Address
from apps.users.utils import generate_verify_token, check_verify_token
from celery_tasks.email.tasks import celery_send_email_code
from utils.viewmixin import LoginMixin


class CheckUsername(View):
    def get(self, request, username):
        count = User.objects.filter(username=username).count()
        if count == 0:
            ret = {
                "count": count,
                "code": "0",
                "errmsg": "OK"
            }
        else:
            ret = {
                "count": count,
                "code": "0",
                "errmsg": "OK"
            }
        return JsonResponse(ret)


class RegisterView(View):
    def post(self, request):
        body_dict = json.loads(request.body)
        username = body_dict.get('username')
        password = body_dict.get('password')
        password2 = body_dict.get('password2')
        mobile = body_dict.get('mobile')
        sms_code = body_dict.get('sms_code')
        allow = body_dict.get('allow')
        if not all([username, password, password2, mobile, sms_code, allow]):
            return JsonResponse({"code": "400", "errmsg": "缺少参数"})

        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return JsonResponse({"code": "400", "errmsg": "手机号码不正确"})

        redis_cli = get_redis_connection('code')
        redis_sms_code = redis_cli.get('sms_%s' % mobile)

        if not redis_sms_code:
            return JsonResponse({"code": "400", "errmsg": "短信验证码已过期"})
        if sms_code != redis_sms_code.decode():
            return JsonResponse({"code": "400", "errmsg": "短信验证码不正确"})
        user = User.objects.create_user(username=username, password=password, mobile=mobile)
        # 状态保持，参1 为request请求  参2 为创建用户时的返回值
        login(request, user)
        ret = JsonResponse({"code": "0", "errmsg": "OK"})
        ret.set_cookie('username', user.username, max_age=3600 * 24 * 5)
        response = merge_cart_cookie_to_redis(request, user, ret)
        return response


class LoginView(View):
    def post(self, request):
        user_dict = json.loads(request.body)
        username = user_dict.get('username')
        password = user_dict.get('password')
        remembered = user_dict.get('remembered')
        if not all([username, password]):
            return JsonResponse({'code': 400, 'errmsg': '缺少参数'})
        if re.match('1[3-9]\d{9}', username):
            User.USERNAME_FIELD = 'mobile'
        else:
            User.USERNAME_FIELD = 'username'
        user = authenticate(username=username, password=password)
        if not user:
            return JsonResponse({'code': 400, 'errmsg': '用户名或密码错误'})

        login(request, user)

        if remembered:
            request.session.set_expiry(None)
        else:
            request.session.set_expiry(0)
        ret = JsonResponse({'code': 0, 'errmsg': 'ok'})
        ret.set_cookie('username', user.username, max_age=3600 * 24 * 5)

        response = merge_cart_cookie_to_redis(request, user, ret)
        return response


class LogoutView(View):
    def delete(self, request):
        logout(request)
        ret = JsonResponse({'code': 0, 'errmsg': 'ok'})
        ret.delete_cookie('username')

        return ret


"""
    显示用户中心上的信息
    继承于LoginMixin  用于登录验证
     request.user就是当前保持状态的用户  返回前端请求数据
"""


class UserInfoView(LoginMixin, View):
    def get(self, request):
        user = request.user
        username = user.username
        mobile = user.mobile
        email = user.email
        email_active = user.email_active
        ret = {
            'code': 0,
            'errmsg': 'ok',
            'info_data': {
                'username': username,
                'mobile': mobile,
                'email': email,
                'email_active': email_active,
            }
        }
        return JsonResponse(ret)


"""
    保存邮箱视图
    获取用户输入要保存的邮箱  前端js有验证邮箱
    校验参数
    保存邮箱到数据库
    并发送一封邮件
    使用itsdangerous工具生成一个token 就是加密后的user_id
    拼接发送的邮件内容
"""


class SaveEmailView(View):
    def put(self, request):
        data_dict = json.loads(request.body)
        email = data_dict.get('email')
        if not email:
            return JsonResponse({'code': 400, 'errmsg': '邮箱地址不能为空'})
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '保存邮箱失败'})
            # 标题
        subject = "美多商城邮箱验证"
        token = generate_verify_token(request.user.id)
        verify_url = 'http://www.meiduo.site:8080/success_verify_email.html?token=%s' % token
        html_message = '<p>尊敬的用户您好!</p>' \
                       '<p>感谢您使用美多商城</p>' \
                       '<p>请点击此链接激活您的邮箱：</p>' \
                       '<p><a href="%s">%s<a></p>' % (verify_url, verify_url)
        from_email = 'rongcunqing@126.com'
        recipient_list = [email]
        celery_send_email_code.delay(subject, from_email, recipient_list, html_message)

        return JsonResponse({'code': 0, 'errmsg': 'ok'})


"""
    用户在邮箱内点进激活的url
    使用itsdangerous解密token校验user_id是否存在
    把数据库用户是否激活的字段该为True
"""


class EmailsVerify(View):
    def put(self, request):
        token = request.GET.get('token')
        if not token:
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})
        user_id = check_verify_token(token)
        user = User.objects.get(id=user_id)
        if not user:
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})
        user.email_active = True
        user.save()

        return JsonResponse({'code': 0, 'errmsg': 'ok'})


# addresses/create/
class CreateAddressView(LoginMixin, View):
    def post(self, request):
        user_data = json.loads(request.body)
        receiver = user_data.get('receiver')
        province_id = user_data.get('province_id')
        city_id = user_data.get('city_id')
        district_id = user_data.get('district_id')
        place = user_data.get('place')
        mobile = user_data.get('mobile')
        tel = user_data.get('tel')
        email = user_data.get('email')

        if not re.match(r'^1[345789]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号输入不正确'})

        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})
        try:
            address = Address.objects.create(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '保存失败'})

        address_dict = {
            'id': address.id,
            'title': address.title,
            'receiver': address.receiver,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email
        }
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'address': address_dict})


# /addresses/
class AddressesView(LoginMixin, View):
    """显示收获地址"""

    def get(self, request):
        user_address_list = Address.objects.filter(user=request.user, is_deleted=False)
        default_address_id = request.user.default_address

        addresses = []
        for address in user_address_list:
            addresses.append({
                'id': address.id,
                'title': address.title,
                'receiver': address.receiver,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'place': address.place,
                'mobile': address.mobile,
                'tel': address.tel,
                'email': address.email
            })

        return JsonResponse(
            {'code': 0, 'errmsg': 'ok', 'addresses': addresses, 'default_address_id': default_address_id})

    """逻辑删除收货地址"""

    def delete(self, request, address_id):

        try:
            delete_address = Address.objects.get(id=address_id)
            delete_address.is_deleted = True
            delete_address.save()
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})

        return JsonResponse({'code': 0, 'errmsg': 'ok'})

    """修改收获地址"""

    def put(self, request, address_id):

        try:
            address = Address.objects.get(id=address_id)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})

        update_dict = json.loads(request.body)
        city_id = update_dict.get('city_id')
        district_id = update_dict.get('district_id')
        mobile = update_dict.get('mobile')
        place = update_dict.get('place')
        province_id = update_dict.get('province_id')
        receiver = update_dict.get('receiver')
        email = update_dict.get('email')
        tel = update_dict.get('tel')

        if not all([city_id, district_id, mobile, place, province_id, receiver]):
            return JsonResponse({'code': 400, 'errmsg': '缺少参数'})
        try:
            address.city_id = city_id
            address.district_id = district_id
            address.mobile = mobile
            address.place = place
            address.province_id = province_id
            address.receiver = receiver
            address.email = email
            address.tel = tel
            address.save()
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '修改失败'})

        address_dict = {
            'id': address.id,
            'title': address.title,
            'receiver': address.receiver,
            'province': address.province.name,
            'city': address.city.name,
            'district': address.district.name,
            'place': address.place,
            'mobile': address.mobile,
            'tel': address.tel,
            'email': address.email
        }
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'address': address_dict})


# /addresses/2/title/
"""修改标题视图"""


class UpdateTitle(LoginMixin, View):
    def put(self, request, update_title_id):
        new_title = json.loads(request.body).get('title')
        if not new_title:
            return JsonResponse({'code': 400, 'errmsg': '缺少参数'})
        try:
            update_title_address = Address.objects.get(id=update_title_id)
            update_title_address.title = new_title
            update_title_address.save()
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})
        return JsonResponse({'code': 0, 'errmsg': 'ok'})


# addresses/3/default/
class UpdateDefault(LoginMixin, View):
    def put(self, request, default_address_id):
        if not default_address_id:
            return JsonResponse({'code': 400, 'errmsg': '缺少参数'})
        try:
            Address.objects.get(id=default_address_id)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})
        else:
            request.user.default_address = default_address_id
            request.user.save()

        return JsonResponse({'code': 0, 'errmsg': 'ok'})


class UpdatePasswordView(LoginMixin, View):
    def put(self, request):
        user = request.user

        password_dict = json.loads(request.body)

        new_password = password_dict.get('new_password')
        new_password2 = password_dict.get('new_password2')
        old_password = password_dict.get('old_password')

        if not all([new_password, new_password2, old_password]):
            return JsonResponse({'code': 400, 'errmsg': '参数错误'})

        if old_password == new_password:
            return JsonResponse({'code': 400, 'errmsg': '设置的新密码不可以和最近使用的一样'})

        if new_password != new_password2:
            return JsonResponse({'code': 400, 'errmsg': '两次密码不一致'})

        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password) and not re.match(r'^[0-9A-Za-z]{8,20}$',
                                                                               new_password2) and re.match(
            r'^[0-9A-Za-z]{8,20}$', old_password):
            return JsonResponse({'code': 400, 'errmsg': '密码格式不正确'})

        is_true_password = check_password(old_password, user.password)
        if not is_true_password:
            return JsonResponse({'code': 400, 'errmsg': '当前密码输入不正确'})

        user.set_password(new_password)
        user.save()

        logout(request)
        ret = JsonResponse({'code': 0, 'errmsg': 'ok'})
        ret.delete_cookie('username')
        return ret
